//
// Created by DELL on 2022/4/20.
//
#pragma once
#include "../Utils.h"
#include "../VulkanDefine.h"

BEGIN_NS_VULKAN

class Model
{
public:
    virtual ~Model();
    Model(const Model&) = delete;
    Model& operator=(const Model&) = delete;

    virtual void bind(VkCommandBuffer commandBuffer);
    virtual void draw(VkCommandBuffer commandBuffer);

protected:

    explicit Model(DeviceRef device);

    virtual void createVertexBuffers(const void* data,  int size);

    DeviceRef device;
    VkBuffer vertexBuffer{};
    VkDeviceMemory vertexBufferMemory{};
    uint32_t vertexCount{};
};

class Model2D : public Model
{
public:

    struct Vertex
    {
        glm::vec2 position;
        glm::vec3 color;

        static std::vector<VkVertexInputBindingDescription> getBindingDescriptions();
        static std::vector<VkVertexInputAttributeDescription> getAttributeDescriptions();
    };

    static Model2DRef create(DeviceRef& device, const std::vector<Vertex>& vertices);

    ~Model2D() override = default;
    Model2D(const Model2D&) = delete;
    Model2D& operator=(const Model2D&) = delete;

protected:

    explicit Model2D(DeviceRef& device);
};

class Model2DTex : public Model
{
public:

    struct Vertex
    {
        glm::vec2 position;
        glm::vec2 texCoord;
        glm::vec3 color;

        static std::vector<VkVertexInputBindingDescription> getBindingDescriptions();
        static std::vector<VkVertexInputAttributeDescription> getAttributeDescriptions();
    };

    static Model2DTexRef create(DeviceRef& device, const std::vector<Vertex>& vertices);

    ~Model2DTex() override = default;
    Model2DTex(const Model2DTex&) = delete;
    Model2DTex& operator=(const Model2D&) = delete;

protected:

    explicit Model2DTex(DeviceRef& device);
};

class Model3D : public Model
{
public:

    struct Vertex
    {
        glm::vec3 position;
        glm::vec2 texCoord;

        static std::vector<VkVertexInputBindingDescription> getBindingDescriptions();
        static std::vector<VkVertexInputAttributeDescription> getAttributeDescriptions();
    };

    static Model3DRef create(DeviceRef& device, const std::vector<Vertex>& vertices);

    ~Model3D() override = default;
    Model3D(const Model3D&) = delete;
    Model3D& operator=(const Model3D&) = delete;

protected:

    explicit Model3D(DeviceRef& device);
};

END_NS_VULKAN